package com.yozi;

import android.app.*;
import android.widget.*;
import android.os.*;

import android.graphics.*;
import android.content.*;

import java.io.*;
import java.nio.*;


import android.util.*;
import android.content.res.Resources;

import android.view.*;
import android.view.ViewGroup.LayoutParams;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;

import com.yozi.*;
import com.swampex.*;

import android.hardware.SensorListener;
import android.hardware.SensorManager;

import android.location.*;

import java.util.List;
import android.content.Intent;

import android.os.PowerManager;
import java.text.DecimalFormat;

import 	android.os.SystemClock;
import 	android.view.animation.*;
import android.view.animation.Animation.AnimationListener;

import android.widget.Toast;

import com.robert.maps.kml.PoiActivity;
import com.robert.maps.kml.PoiListActivity;
import com.robert.maps.kml.PoiViewActivity;
import com.robert.maps.kml.PoiManager;
import com.robert.maps.kml.PoiPoint;
import com.robert.maps.kml.PoiFileList;
import com.robert.maps.kml.Track;
import com.robert.maps.kml.TrackListActivity;
import com.robert.maps.utils.Ut;

import com.robert.maps.utils.NinePatch;
import com.robert.maps.utils.NinePatchDrawable;

import org.andnav.osm.util.GeoPoint;
import android.graphics.Paint.Style;

import android.graphics.DashPathEffect;

import org.openintents.filemanager.util.FileUtils;
		
/*----------------------------------------------------------------------------*/
public class yozi extends Activity
{
    private LocationManager mLocationManager	= null;


	int surface_dx = 0;
	int surface_dy = 0;

	private PoiManager mPoiManager = null;
    private TopoView topoView = null;
	protected PowerManager.WakeLock wl;
	
	private Geocoder geocoder = null;
	
	long	lastRenderTime = 0;


	ScaleAnimation scaleAnimation = null;    
    

	Toast mToast = null;
	boolean renderingInProgress = false;



/*----------------------------------------------------------------------------*/
    private String llToString(double inValue)
    {
		DecimalFormat fmt = new DecimalFormat("00.000000");
		String shortString = (fmt.format(inValue));
		return shortString;
	}

/*----------------------------------------------------------------------------*/
	private final void updateTitle()
	{
		double lat = Swampex.getLocationLat();
		double lon = Swampex.getLocationLon();
		
		String pos = llToString(lat) + " " + llToString(lon);
		
		setTitle(pos);
	}


	

/*----------------------------------------------------------------------------*/
	private final void updateRender()
	{
		Thread t = new Thread() 
		{
            public void run() 
            {
				topoView.setSurface(Swampex.getMapSurface());
				topoView.update();
				renderingInProgress = false;
            }
        };
        t.start();	
	
    }

	private final void zoomOut()
	{
		Thread t = new Thread() 
		{
            public void run() 
            {
				Swampex.zoomOut();
				topoView.setSurface(Swampex.getMapSurface());
				topoView.clearAnimation();

				topoView.setDrawCursor(true);
				topoView.update();
//				hideWaitDialog();
            }
        };
        t.start();	
    }

	private final void zoomIn()
	{
		Thread t = new Thread() 
		{
            public void run() 
            {
				Swampex.zoomIn();
				topoView.setSurface(Swampex.getMapSurface());
				topoView.clearAnimation();

				topoView.setDrawCursor(true);
				topoView.update();
//				hideWaitDialog();
            }
        };
        t.start();	
    }



/*----------------------------------------------------------------------------*/
    private final LocationListener mLocationListener = new LocationListener() 
	{
		@Override
		public void onLocationChanged(Location location) 
		{

			if (topoView.getAutoFollow() == true)
			{

				if (renderingInProgress == true)
					return;
    								
    			long currentTime = android.os.SystemClock.uptimeMillis();
    			
    			// one rendering per second
    			if ( currentTime - lastRenderTime >= 1000 ) 
    			{ 
					renderingInProgress = true;

    				lastRenderTime = currentTime;

    				topoView.setBearing(location.getBearing());

        			Swampex.setLocation(location.getLatitude(), 
        								location.getLongitude());

    				updateRender();
    			}
			}											
		}    

		@Override
		public void onProviderDisabled(String provider) 
		{
			//dragEnabled = true;
		}    

		@Override
		public void onProviderEnabled(String provider) 
		{
			//dragEnabled = false;
		}    

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) 
		{
		}
	};

/*----------------------------------------------------------------------------*/
    private final View.OnClickListener zoomInListener = new View.OnClickListener () 
	{

        public void onClick(View v) 
		{

			double zoom_current = Swampex.getZoom();
			double zoom_next = Swampex.getZoomNext();

			if (zoom_next == 0.0)
				return;

			double factor = zoom_next / zoom_current;

   			long animationDuration = 1500;
			
			scaleAnimation = 
			new ScaleAnimation((float)1, (float)factor, (float)1, (float)factor, 
        		(int)ScaleAnimation.RELATIVE_TO_SELF, (float)0.5f, 
        		(int)ScaleAnimation.RELATIVE_TO_SELF, (float)0.5f);

        	scaleAnimation.setDuration(animationDuration);

			scaleAnimation.setAnimationListener(new AnimationListener() 
			{

                public void onAnimationStart(Animation animation) {
					topoView.setDrawCursor(false);
                }

                public void onAnimationRepeat(Animation animation) {
                }

                public void onAnimationEnd(Animation animation) {
                }
	        });

			topoView.setAnimation(scaleAnimation);
			topoView.invalidate();

//			showWaitDialog();
			zoomIn();
        }
    };

/*----------------------------------------------------------------------------*/
    private final View.OnClickListener zoomOutListener = new View.OnClickListener () 
	{       

        public void onClick(View v) 
		{

			double zoom_current = Swampex.getZoom();
			double zoom_prev = Swampex.getZoomPrev();

			if (zoom_prev == 0.0)
				return;

			double factor = zoom_prev / zoom_current;

   			long animationDuration = 1500;

			scaleAnimation = 
			new ScaleAnimation((float)1, (float)factor, (float)1, (float)factor, 
        		(int)ScaleAnimation.RELATIVE_TO_SELF, (float)0.5f, 
        		(int)ScaleAnimation.RELATIVE_TO_SELF, (float)0.5f);

        	scaleAnimation.setDuration(animationDuration);


			scaleAnimation.setAnimationListener(new AnimationListener() 
			{

                public void onAnimationStart(Animation animation) {
					topoView.setDrawCursor(false);
                }

                public void onAnimationRepeat(Animation animation) {
                }

                public void onAnimationEnd(Animation animation) {
                }
        	});

			topoView.setAnimation(scaleAnimation);
			topoView.invalidate();

//			showWaitDialog();
			zoomOut();
			
        }
    };


	private final void nextMap()
	{
		Thread t = new Thread() 
		{
            public void run() 
            {
				Swampex.nextMap();
				topoView.setSurface(Swampex.getMapSurface());
				topoView.clearAnimation();

				topoView.setDrawCursor(true);
				topoView.update();
//				hideWaitDialog();
            }
        };
        t.start();	
    }

	private final void prevMap()
	{
		Thread t = new Thread() 
		{
            public void run() 
            {
				Swampex.prevMap();
				topoView.setSurface(Swampex.getMapSurface());
				topoView.clearAnimation();

				topoView.setDrawCursor(true);
				topoView.update();
//				hideWaitDialog();
            }
        };
        t.start();	
    }


    private final View.OnClickListener nextMapListener = new View.OnClickListener () 
	{       
        public void onClick(View v) 
		{
//			showWaitDialog();
			nextMap();
		}
	};

    private final View.OnClickListener prevMapListener = new View.OnClickListener () 
	{       
        public void onClick(View v) 
		{
//			showWaitDialog();
			prevMap();
		}
	};


	void showWaitDialog()
	{
		if (mToast != null)
		{
			hideWaitDialog();
		}
		mToast = Toast.makeText(this, "Wait", Toast.LENGTH_SHORT);
		mToast.setGravity(Gravity.CENTER, 0, 0);
		mToast.show();
	}

	void hideWaitDialog()
	{
		if (mToast != null)
		{
			mToast.cancel();
			mToast = null;
		}
	}

/*----------------------------------------------------------------------------*/
	public void setFullscreen() 
	{
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
   
/*----------------------------------------------------------------------------*/
    public void setNoTitle() 
	{
        requestWindowFeature(Window.FEATURE_NO_TITLE);
    } 


	private void setLastKnownLocation() {
		final LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		final Location loc1 = lm.getLastKnownLocation("gps");
		final Location loc2 = lm.getLastKnownLocation("network");

		boolean boolGpsEnabled = lm.isProviderEnabled("gps");
		boolean boolNetworkEnabled = lm.isProviderEnabled("network");
		String str = "";
		Location loc = null;

		if(loc1 == null && loc2 != null)
			loc = loc2;
		else if (loc1 != null && loc2 == null)
			loc = loc1;
		else if (loc1 == null && loc2 == null)
			loc = null;
		else
			loc = loc1.getTime() > loc2.getTime() ? loc1 : loc2;

		if(boolGpsEnabled){}
		else if(boolNetworkEnabled)
			str = "GPS disabled"; //getString(R.string.message_gpsdisabled);
		else if(loc == null)
			str = "Location unavailable"; //getString(R.string.message_locationunavailable);
		else
			str = ""; //getString(R.string.message_lastknownlocation);

		if(str.length() > 0)
			Toast.makeText(this, str, Toast.LENGTH_LONG).show();

   		Swampex.setLocation(loc.getLatitude(), 
   							loc.getLongitude());
   							
   		updateRender();
	}


/*----------------------------------------------------------------------------*/
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Display display = getWindowManager().getDefaultDisplay(); 
        surface_dx = display.getWidth();
        surface_dy = display.getHeight();

		setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);

		setNoTitle();

        installData();

		Swampex.initDatums("/data/data/com.yozi/files/datums.xml");
		Swampex.initMaps("/sdcard/maps", surface_dx, surface_dy);

        mPoiManager = new PoiManager(this);

		

		mLocationManager = 
			(LocationManager) getSystemService(LOCATION_SERVICE);
			
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My Tag");
		wl.acquire();
		
		Location location = mLocationManager.getLastKnownLocation("gps");
		
		if (location != null)
		{
			Swampex.setLocation(location.getLatitude(), 
								location.getLongitude());
		}

        setContentView(R.layout.mapview);

		topoView = (TopoView)findViewById(R.id.mapview);
		topoView.initialize(surface_dx, surface_dy);
		topoView.setPoiManager(mPoiManager);
		topoView.setSurface(Swampex.getMapSurface());

		ImageButton button = (ImageButton)findViewById(R.id.zoomin);
		button.setOnClickListener(zoomInListener);
		button = (ImageButton)findViewById(R.id.zoomout);
		button.setOnClickListener(zoomOutListener);
		button = (ImageButton)findViewById(R.id.prevmap);
		button.setOnClickListener(prevMapListener);
		button = (ImageButton)findViewById(R.id.nextmap);
		button.setOnClickListener(nextMapListener);

		registerForContextMenu(topoView);



    }


/*----------------------------------------------------------------------------*/
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) 
	{
		switch(requestCode)
		{
      		case R.id.poilist:
      			if(resultCode == RESULT_OK)
      			{
      				PoiPoint point = mPoiManager.getPoiPoint(data.getIntExtra("pointid", PoiPoint.EMPTY_ID()));
      				if(point != null)
      				{
      					topoView.setAutoFollow(false);
      	    			Swampex.setLocation(point.GeoPoint.getLatitude(), 
          									point.GeoPoint.getLongitude());
          		    	updateRender();
      				}
					else
					{
						point = mPoiManager.getPoiPoint(data.getIntExtra("pointid-target", PoiPoint.EMPTY_ID()));
        				if(point != null)
        				{
							topoView.setSelectedPointID(point.getId());
							topoView.update();
        				}
					}
      			}
      			break;
		}

		super.onActivityResult(requestCode, resultCode, data);
	}

/*----------------------------------------------------------------------------*/
	@Override
    public boolean onCreateOptionsMenu(final Menu pMenu) 
    {
        MenuItem settingsMenuItem = 
        	pMenu.add(0, R.id.menu_gpssettings, Menu.NONE, "GPS Settings");
        
        settingsMenuItem.setIcon(android.R.drawable.ic_menu_preferences);

        MenuItem locationMenuItem = 
        	pMenu.add(0, R.id.menu_autofollow, Menu.NONE, "AutoFollow");
        
        locationMenuItem.setIcon(android.R.drawable.ic_menu_mylocation);

        MenuItem searchMenuItem = 
        	pMenu.add(0, R.id.menu_searchfor, Menu.NONE, "Search for place");
        	
        searchMenuItem.setIcon(android.R.drawable.ic_menu_search);
        
        MenuItem poiMenuItem = 
        	pMenu.add(0, R.id.menu_poilist, Menu.NONE, "POI");
        	
        poiMenuItem.setIcon(android.R.drawable.ic_menu_myplaces);

        MenuItem addPoiMenuItem = 
        	pMenu.add(0, R.id.menu_addpoi, Menu.NONE, "Add POI");
        	
        addPoiMenuItem.setIcon(android.R.drawable.ic_menu_add);

        MenuItem aboutMenuItem = 
        	pMenu.add(0, R.id.menu_about, Menu.NONE, "About");
        	
        aboutMenuItem.setIcon(android.R.drawable.ic_menu_info_details);

        return true;
	}

/*----------------------------------------------------------------------------*/
	public void  onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)  
	{
		menu.add(0, R.id.menu_toradar, 0, getText(R.string.menu_toradar));
		menu.add(0, R.id.menu_details, 0, getText(R.string.menu_details));
		menu.add(0, R.id.menu_unselect, 0, "Unselect");
		menu.add(0, R.id.menu_deletepoi, 0, getText(R.string.menu_delete));

		super.onCreateContextMenu(menu, v, menuInfo);
	}
 

/*----------------------------------------------------------------------------*/
	@Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) 
    {
		int pointid = topoView.getSelectedPointID();
		PoiPoint poi = mPoiManager.getPoiPoint(pointid);

        switch (item.getItemId()) 
        {
	        case R.id.menu_gpssettings:
				startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
				return true;

			case R.id.menu_unselect:
				topoView.setSelectedPointID(-1);
    			topoView.invalidate();
				return true;

			case R.id.menu_autofollow:
			{
			    if (topoView.getAutoFollow() == false)
				{
					topoView.setAutoFollow(true);
				}
				else
				{
					topoView.setAutoFollow(false);
					topoView.setBearing(0);
				}
				
				return true;
			}

	        case R.id.menu_searchfor:
				onSearchRequested();
				return true;
			
			case R.id.menu_poilist:
			{
				startActivityForResult(new Intent(this, PoiListActivity.class), R.id.poilist);
				//mItemList = null;
				topoView.poiChanged();
				return true;
			}

			case R.id.menu_addpoi:
			{
				startActivity((new Intent(this, PoiActivity.class))
						.putExtra("lat", Swampex.getLocationLat()).putExtra("lon", Swampex.getLocationLon()).putExtra("title", "POI"));
				topoView.poiChanged();
				return true;
			}

			case R.id.menu_about:
			{
				showDialog(R.id.about);
				return true;
			}

			case R.id.menu_details:
				startActivity((new Intent(this, PoiViewActivity.class)).putExtra("pointid", pointid));
				return true;
			case R.id.menu_deletepoi:
				topoView.setSelectedPointID(-1);
				mPoiManager.deletePoi(pointid);
				topoView.poiChanged();
    			topoView.invalidate();
				return true;
			case R.id.menu_toradar:
				try 
				{
					Intent i = new Intent("com.google.android.radar.SHOW_RADAR");
					i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
					i.putExtra("name", poi.Title);
					i.putExtra("latitude",  (float)(poi.GeoPoint.getLatitudeE6() / 1000000f));
					i.putExtra("longitude", (float)(poi.GeoPoint.getLongitudeE6() / 1000000f));
					startActivity(i);
				} 
				catch (Exception e) 
				{
					Toast.makeText(this, R.string.message_noradar, Toast.LENGTH_LONG).show();
				}
                return true;

        }

        return false;
    }

	@Override
	protected Dialog onCreateDialog(int id) 
	{
		switch (id) 
		{
		case R.id.about:
			return new AlertDialog.Builder(this) //.setIcon(R.drawable.alert_dialog_icon)
					.setTitle(R.string.menu_about)
					.setMessage(getText(R.string.app_name) + " v." + Ut.getAppVersion(this) + "\n\n"
							+ getText(R.string.about_dialog_text))
/*					.setPositiveButton(R.string.about_dialog_whats_new, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {

							showDialog(R.id.whatsnew);
						}
					})*/.setNegativeButton(R.string.about_dialog_close, new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int whichButton) {

							/* User clicked Cancel so do some stuff */
						}
					}).create();
		}
		return null;
	}
/*----------------------------------------------------------------------------*/
	@Override
	public boolean onSearchRequested() 
	{
		AlertDialog.Builder builder = new AlertDialog.Builder(yozi.this);
		
		builder.setCancelable(true);
		builder.setTitle("Search for place:");

		final EditText editBox = new EditText(this);
		builder.setView(editBox);

		builder.setPositiveButton("Search", new DialogInterface.OnClickListener() 
		{
			public void onClick(DialogInterface dialog, int whichButton) 
			{
				final String message = editBox.getText().toString();

				if (message.length() != 0)
				{
					geocoder = new Geocoder(yozi.this);

					List<Address> addresses = null;
					try
					{
						addresses = geocoder.getFromLocationName(message, 1);
					}
					catch(Exception e){}

					if (addresses != null)
					{
    					if (addresses.isEmpty() == false)
    					{
        					topoView.setAutoFollow(false);
        					topoView.setBearing(0);

    						Swampex.setLocation(addresses.get(0).getLatitude(), 
    											addresses.get(0).getLongitude());
    											
    						updateRender();
    					}
					}
				}
            }
        });

        builder.show();

		return false;
	}

/*----------------------------------------------------------------------------*/
    @Override
    protected void onResume()
    {
        super.onResume();

		if ( mLocationManager != null ) 
		{ 
			mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 
													0, 
													0, 
													mLocationListener);
		}
    }

/*----------------------------------------------------------------------------*/
    @Override
    protected void onStop()
    {

		if (mLocationManager != null)
                mLocationManager.removeUpdates(mLocationListener);
                
        super.onStop();
    }


/*----------------------------------------------------------------------------*/
    void installRawResource(int id, String path)
    {
        InputStream in = getResources().openRawResource(id);

        FileOutputStream out = null;

        try
        {
            out = openFileOutput(path, MODE_PRIVATE);

            int size = in.available();

            byte[] buffer = new byte[size];
            in.read(buffer);
            in.close();

            out.write(buffer);
            out.close();

        }
        catch(Exception e){}
    }

/*----------------------------------------------------------------------------*/
    void installData()
    {
        installRawResource(R.raw.datums, "datums.xml");
    }

	@Override
	protected void onDestroy() {
		Log.d("SWAMPEX", "cleaning up");
		Swampex.cleanup();
		mPoiManager.FreeDatabases();
		super.onDestroy();
	}




}









